﻿using System;
using System.Collections.Generic;
using System.Reflection;

namespace Pro.Common.IoC
{
    public interface IAssemblySource
    {
        IEnumerable<Assembly> GetAssemblies();
    }

    public interface ITypeSource
    {
        IEnumerable<Type> GetTypes();
    }

    public interface IAssemblySourceBuilder
    {
        void IncludeAssembliesInBaseDirectory();

        void IncludeAssembliesInBaseDirectory(Predicate<Assembly> predicate);

        void IncludeAssembliesInDirectory(string path);

        void IncludeAssembliesInDirectory(string path, Predicate<Assembly> predicate);

        void IncludeAssembly(Assembly assembly);

        IAssemblySource Build();
    }

    public interface IComponentRegistry
    {
        int Priority { get; }

        void Configure(IComponentContainerConfigurator componentContainerConfigurator);
    }

    public interface IComponentContainerConfigurator
    {
        void RegisterType<TComponent>();

        void RegisterType<TComponent>(string componentName);

        void RegisterType<TComponentFrom, TComponentTo>() where TComponentTo : TComponentFrom;

        void RegisterType<TComponentFrom, TComponentTo>(string componentName) where TComponentTo : TComponentFrom;

        void RegisterType(Type componentType);

        void RegisterType(Type componentType, string componentName);

        void RegisterType(Type componentFrom, Type componentTo);

        void RegisterType(Type componentFrom, Type componentTo, string componentName);

        void RegisterInstance<TComponent>(TComponent componentInstance);

        void RegisterInstance<TComponent>(TComponent componentInstance, string componentInstanceName);
    }

    public interface IEngine
    {
        T Resolve<T>();
        T Resolve<T>(string componentName);

        IEnumerable<T> ResolveAll<T>();

        object Resolve(Type componentType);
        object Resolve(Type componentType, string componentName);

        IEnumerable<object> ResolveAll(Type componentType);

        bool TryResolve(Type componentType, out object componentInstance);
        bool TryResolve(Type componentType, string componentName, out object componentInstance);

        bool TryResolve(Type componentType, out IEnumerable<object> componentInstances);
    }
}